


// Example settings (grey 2x16 LCD, double zoom)
//   #define guiemu_ENABLED
//   #define lcdNUMBER_OF_CHARACTERS 16
//   #define lcdNUMBER_OF_LINES 2
//   #define guiemu_ZOOM 2
//   #define guiemu_BACKLIGHT_COLOR RGB(0xa0, 0xff, 0)
//   #define guiemu_BACKGROUND_COLOR RGB(0x80, 0xe8, 0)
//   #define guiemu_FOREGROUND_COLOR RGB(0, 0, 0)
// or change the last three lines for blue display
//   #define guiemu_BACKLIGHT_COLOR RGB(0xa0, 0xff, 0)
//   #define guiemu_BACKGROUND_COLOR RGB(0x80, 0xe8, 0)
//   #define guiemu_FOREGROUND_COLOR RGB(0, 0, 0)


#include <windows.h>
#include <tchar.h>
#include "sysSettings.h"
#include "krnlTypes.h"

///////////////////////////////////////////////////////////////////////////////
// Const
#define guiCHARACTER_WIDTH 5
#define guiCHARACTER_HEIGHT 8
#define guiCHARACTER_GAP 1
#define guiLINE_GAP 1
#define guiBORDER_SIZE 5
#define guiUSER_DEFINABLE_CHARACTERS 8

#define guiSCREEN_WIDTH ((guiCHARACTER_WIDTH + guiCHARACTER_GAP) * lcdNUMBER_OF_CHARACTERS - guiCHARACTER_GAP)
#define guiSCREEN_HEIGHT ((guiCHARACTER_HEIGHT + guiLINE_GAP) * lcdNUMBER_OF_LINES - guiLINE_GAP)

///////////////////////////////////////////////////////////////////////////////
// Display data buffer
static BYTE l_display_buffer[lcdNUMBER_OF_LINES * lcdNUMBER_OF_CHARACTERS];
static BYTE l_character_buffer[4 * guiCHARACTER_HEIGHT];

///////////////////////////////////////////////////////////////////////////////
// Module global variables
static DWORD	l_thread_id			= 0;
static HANDLE	l_thread_handle = NULL;
static HWND		l_hwnd					= 0;
static HBRUSH	l_back_brush		= NULL;
static BYTE  l_bitmapheader[ sizeof( BITMAPINFOHEADER ) + 2 * sizeof( RGBQUAD ) ];
extern BYTE l_charmap[][guiCHARACTER_HEIGHT-1];
static BYTE l_custom_charmap[guiUSER_DEFINABLE_CHARACTERS][guiCHARACTER_HEIGHT];
static BYTE l_cursor_x;
static BYTE l_cursor_y;

///////////////////////////////////////////////////////////////////////////////
// Function prototypes
static void ThreadRoutine( void* in_param );
static HWND CreateCharLCDEmuWindow(void);
static void UpdateEmulationWindow(HDC in_hdc);
extern void EmulatorProcessCharacter(dosBool in_extended, dosChar in_char);

///////////////////////////////////////////////////////////////////////////////
// Functions
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Init emulator window
void drvLCDInit(void)
{
	l_thread_handle = CreateThread( NULL,
																	0,
																	(LPTHREAD_START_ROUTINE)ThreadRoutine,
																	NULL,
																	0,
																	&l_thread_id );

	l_cursor_x = 0;
	l_cursor_y = 0;
}

///////////////////////////////////////////////////////////////////////////////
// Display Clear
void drvLCDClearDisplay(void)
{
	int i;

	for( i = 0; i < lcdNUMBER_OF_LINES * lcdNUMBER_OF_CHARACTERS; i++ )
	{																
		l_display_buffer[i] = ' ';
	}
}

///////////////////////////////////////////////////////////////////////////////
// Moves cursor to the specified coordinates
dosBool drvLCDGotoXY( dosByte in_x, dosByte in_y )
{
	dosBool success = dosTrue;

	// coordinates starts from 1
	in_y--;
	in_x--;

	// check if coordinates within range
	if( in_y < lcdNUMBER_OF_LINES && in_x < lcdNUMBER_OF_CHARACTERS )
	{
		l_cursor_x = in_x;
		l_cursor_y = in_y;
	}
	else
		success = dosFalse;

	return success;
}   

///////////////////////////////////////////////////////////////////////////////
// Write character
void drvLCDWriteCharacter( dosChar in_char )
{
	l_display_buffer[l_cursor_y * lcdNUMBER_OF_CHARACTERS + l_cursor_x] = in_char;

	l_cursor_x++;
	if( l_cursor_x >= lcdNUMBER_OF_CHARACTERS )
	{
		l_cursor_x = 0;
		l_cursor_y++;

		if( l_cursor_y >= lcdNUMBER_OF_LINES )
			l_cursor_y = 0;
	}

	InvalidateRect( l_hwnd, NULL, FALSE );
}

///////////////////////////////////////////////////////////////////////////////
// download custom character
void drvLCDDowloadCustomCharacter( dosByte in_index, const dosByte* in_characters )
{
	int line;

	for( line = 0; line < guiCHARACTER_HEIGHT; line++ )
	{
		l_custom_charmap[in_index][line] = in_characters[line];
	}
}

///////////////////////////////////////////////////////////////////////////////
// Load custom characters
void drvLCDDowloadCustomCharacters( const dosByte* in_characters )
{
	int ch;

	for( ch = 0; ch < guiUSER_DEFINABLE_CHARACTERS; ch++ )
	{
		drvLCDDowloadCustomCharacter( ch, in_characters + ch * guiCHARACTER_HEIGHT );
	}
}

///////////////////////////////////////////////////////////////////////////////
// Is emulator running
dosBool IsEmulatorRunning(void)
{
	Sleep(0);

	return l_thread_handle != NULL;
}

///////////////////////////////////////////////////////////////////////////////
// Internal functions
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Window message handler
static LRESULT CALLBACK WindowMessageHandler(	HWND		in_hwnd,
																							UINT		in_message,
																							WPARAM	in_wparam,
																							LPARAM	in_lparam )
{
  switch (in_message)
  {
		case WM_CREATE:
		{
			// set size
			RECT work_area;
			RECT owner_rect;
			HWND owner_hwnd;
			RECT client_rect;
			RECT window_rect;
			int width, height;
			int left, top;
			BITMAPINFOHEADER* bih;
			RGBQUAD* color;
   			
			// fill bitmap structure
			bih = (BITMAPINFOHEADER*)l_bitmapheader;

			bih->biSize						= sizeof( BITMAPINFOHEADER ); 
			bih->biWidth					= guiCHARACTER_WIDTH; 
			bih->biHeight					= -guiCHARACTER_HEIGHT; 
			bih->biPlanes					= 1; 
			bih->biBitCount				= 1;
			bih->biCompression		= BI_RGB; 
			bih->biSizeImage			= sizeof(l_character_buffer);
			bih->biXPelsPerMeter	= 0; 
			bih->biYPelsPerMeter	= 0; 
			bih->biClrUsed				= 0; 
			bih->biClrImportant		= 0;

			color = (RGBQUAD*)(l_bitmapheader + sizeof(BITMAPINFOHEADER));

			color->rgbRed  = GetRValue( guiemu_BACKGROUND_COLOR );
			color->rgbGreen = GetGValue( guiemu_BACKGROUND_COLOR );
			color->rgbBlue = GetBValue( guiemu_BACKGROUND_COLOR );

			color++;

			color->rgbRed  = GetRValue( guiemu_FOREGROUND_COLOR );
			color->rgbGreen = GetGValue( guiemu_FOREGROUND_COLOR );
			color->rgbBlue = GetBValue( guiemu_FOREGROUND_COLOR );

			// set window size
			GetClientRect(in_hwnd, &client_rect);
			GetWindowRect(in_hwnd, &window_rect );

			width = window_rect.right - window_rect.left;
			height = window_rect.bottom - window_rect.top;

			width		= guiSCREEN_WIDTH * guiemu_ZOOM + 2*guiBORDER_SIZE + width - client_rect.right;
			height	= guiSCREEN_HEIGHT * guiemu_ZOOM + 2*guiBORDER_SIZE + height - client_rect.bottom;

			owner_hwnd = GetDesktopWindow();

			GetWindowRect( owner_hwnd, &owner_rect );

			left = ( owner_rect.left + owner_rect.right	- width		) / 2;
			top = ( owner_rect.top  + owner_rect.bottom	- height	) / 2;

			// center within screen coordinates
			SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0);

			if( left < work_area.left )
				left = work_area.left;

			if( top < work_area.top )
				top = work_area.top;

			if( left + width > work_area.right )
				left = work_area.right - width;

			if( top + height> work_area.bottom )
				top = work_area.bottom - height;

			SetWindowPos( in_hwnd,
										NULL,
										left,
										top,
										width, height,
										SWP_NOZORDER | SWP_NOACTIVATE);
		}
		break;

    case WM_PAINT:
			{
				PAINTSTRUCT ps;
				HDC hdc;

				hdc = BeginPaint(in_hwnd, &ps);

				UpdateEmulationWindow( hdc );

				EndPaint(in_hwnd, &ps);
			}
			break;

		case WM_DESTROY:
			PostQuitMessage(0);
      break;

		case WM_KEYDOWN:
			//EmulatorProcessCharacter( (in_lparam & (1<<24)) != 0, (dosChar)in_wparam );
			break;

		default:
      return DefWindowProc(in_hwnd, in_message, in_wparam, in_lparam);
      break;
    }

    return 0;
}

///////////////////////////////////////////////////////////////////////////////
// Update emulation window
static void UpdateEmulationWindow(HDC in_hdc )
{
	int i;
	int line;
	int col;
	
	for( line = 0; line < lcdNUMBER_OF_LINES; line++ )
	{
		for( col = 0; col < lcdNUMBER_OF_CHARACTERS; col++ )
		{
			if( l_display_buffer[line * lcdNUMBER_OF_CHARACTERS + col] >= guiUSER_DEFINABLE_CHARACTERS )
			{
				for( i = 0; i < guiCHARACTER_HEIGHT - 1; i++ )
				{
					l_character_buffer[i*4] = l_charmap[l_display_buffer[line * lcdNUMBER_OF_CHARACTERS + col]-guiUSER_DEFINABLE_CHARACTERS][i] << 3;
				}

				l_character_buffer[i*4] = 0;
			}
			else
			{
				for( i = 0; i < guiCHARACTER_HEIGHT; i++ )
				{
					l_character_buffer[i*4] = (BYTE)(l_custom_charmap[l_display_buffer[line * lcdNUMBER_OF_CHARACTERS + col]][i] << 3);
				}
			}

			StretchDIBits( in_hdc,
							 col * ((guiCHARACTER_WIDTH + guiCHARACTER_GAP)* guiemu_ZOOM) + guiBORDER_SIZE, line * ((guiCHARACTER_HEIGHT + guiLINE_GAP)* guiemu_ZOOM) + guiBORDER_SIZE,
							 guiCHARACTER_WIDTH*guiemu_ZOOM, guiCHARACTER_HEIGHT*guiemu_ZOOM,
							 0, 0,
							 guiCHARACTER_WIDTH, guiCHARACTER_HEIGHT,
							 l_character_buffer,
							 (BITMAPINFO*)l_bitmapheader,
							 DIB_RGB_COLORS,
							 SRCCOPY );
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
// Create window
static HWND CreateCharLCDEmuWindow(void)
{
	HWND hwnd;

	// register class
	WNDCLASSEX wcex;

	l_back_brush = CreateSolidBrush(guiemu_BACKLIGHT_COLOR);

	wcex.cbSize					= sizeof(WNDCLASSEX);
	wcex.style          = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc    = WindowMessageHandler;
	wcex.cbClsExtra     = 0;
	wcex.cbWndExtra     = 0;
	wcex.hInstance      = 0;
	wcex.hIcon          = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground  = l_back_brush;
	wcex.lpszMenuName   = NULL;
	wcex.lpszClassName  = _T("dosCharLCDEmulationWindow");
	wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

  if(!RegisterClassEx(&wcex))
  {
		MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("dosEmuWin"), 0);

    return 0;
  }

	// create window
	hwnd= CreateWindow(	_T("dosCharLCDEmulationWindow"),
											_T("Domino Operation System Emulation"),
											WS_OVERLAPPEDWINDOW | WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX,
											CW_USEDEFAULT, CW_USEDEFAULT,
											0, 0,
											NULL,
											NULL,
											0,
											NULL );
	if( !hwnd )
	{
		MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("DominoOS Emu"), 0);

    return 0;
	}

	if( hwnd != 0 )
	{
		ShowWindow(hwnd, SW_SHOWNORMAL);
		UpdateWindow(hwnd);
	}

	return hwnd;
}

///////////////////////////////////////////////////////////////////////////////
// Thread functions
static void ThreadRoutine( void* in_param )
{
	MSG msg;
	
	l_hwnd = CreateCharLCDEmuWindow();

	if( l_hwnd != 0 )
	{
		// Main message loop:
		while (GetMessage(&msg, NULL, 0, 0)) 
		{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
				Sleep(0);
		}
	}

	if( l_hwnd != 0 )
		DestroyWindow( l_hwnd );
		
	if( l_back_brush != NULL )
		DeleteObject(l_back_brush);

	l_thread_id			= 0;
	l_thread_handle = NULL;

	ExitThread( 0 );
}

///////////////////////////////////////////////////////////////////////////////
// HD44780 standard character map
static BYTE l_charmap[][guiCHARACTER_HEIGHT-1] = 
{
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{4, 4, 4, 4, 4, 0, 4},
	{10, 10, 10, 0, 0, 0, 0},
	{10, 10, 31, 10, 31, 10, 10},
	{4, 15, 20, 14, 5, 30, 4},
	{24, 25, 2, 4, 8, 19, 3},
	{12, 18, 20, 8, 21, 18, 13},
	{12, 4, 8, 0, 0, 0, 0},
	{2, 4, 8, 8, 8, 4, 2},
	{8, 4, 2, 2, 2, 4, 8},
	{0, 4, 21, 14, 21, 4, 0},
	{0, 4, 4, 31, 4, 4, 0},
	{0, 0, 0, 0, 12, 4, 8},
	{0, 0, 0, 31, 0, 0, 0},
	{0, 0, 0, 0, 0, 12, 12},
	{0, 1, 2, 4, 8, 16, 0},
	{14, 17, 19, 21, 25, 17, 14},
	{4, 12, 4, 4, 4, 4, 14},
	{14, 17, 1, 2, 4, 8, 31},
	{31, 2, 4, 2, 1, 17, 14},
	{2, 6, 10, 18, 31, 2, 2},
	{31, 16, 30, 1, 1, 17, 14},
	{6, 8, 16, 30, 17, 17, 14},
	{31, 1, 2, 4, 8, 8, 8},
	{14, 17, 17, 14, 17, 17, 14},
	{14, 17, 17, 15, 1, 2, 12},
	{0, 12, 12, 0, 12, 12, 0},
	{0, 12, 12, 0, 12, 4, 8},
	{2, 4, 8, 16, 8, 4, 2},
	{0, 0, 31, 0, 31, 0, 0},
	{16, 8, 4, 2, 4, 8, 16},
	{14, 17, 1, 2, 4, 0, 4},
	{14, 17, 1, 13, 21, 21, 14},
	{14, 17, 17, 17, 31, 17, 17},
	{30, 17, 17, 30, 17, 17, 30},
	{14, 17, 16, 16, 16, 17, 14},
	{30, 17, 17, 17, 17, 17, 30},
	{31, 16, 16, 30, 16, 16, 31},
	{31, 16, 16, 30, 16, 16, 16},
	{14, 17, 16, 23, 17, 17, 15},
	{17, 17, 17, 31, 17, 17, 17},
	{14, 4, 4, 4, 4, 4, 14},
	{7, 2, 2, 2, 2, 18, 12},
	{17, 18, 20, 24, 20, 18, 17},
	{16, 16, 16, 16, 16, 16, 31},
	{17, 27, 21, 21, 17, 17, 17},
	{17, 17, 25, 21, 19, 17, 17},
	{14, 17, 17, 17, 17, 17, 14},
	{30, 17, 17, 30, 16, 16, 16},
	{14, 17, 17, 17, 21, 18, 13},
	{30, 17, 17, 30, 20, 18, 17},
	{15, 16, 16, 14, 1, 1, 30},
	{31, 4, 4, 4, 4, 4, 4},
	{17, 17, 17, 17, 17, 17, 14},
	{17, 17, 17, 17, 17, 10, 4},
	{17, 17, 17, 21, 21, 21, 10},
	{17, 17, 10, 4, 10, 17, 17},
	{17, 17, 17, 10, 4, 4, 4},
	{31, 1, 2, 4, 8, 16, 31},
	{14, 8, 8, 8, 8, 8, 14},
	{17, 10, 31, 4, 31, 4, 4},
	{14, 2, 2, 2, 2, 2, 14},
	{4, 10, 17, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 31},
	{8, 4, 2, 0, 0, 0, 0},
	{0, 0, 14, 1, 15, 17, 15},
	{16, 16, 22, 25, 17, 17, 30},
	{0, 0, 14, 16, 16, 17, 14},
	{1, 1, 13, 19, 17, 17, 15},
	{0, 0, 14, 17, 31, 16, 14},
	{6, 9, 8, 28, 8, 8, 8},
	{0, 0, 15, 17, 15, 1, 14},
	{16, 16, 22, 25, 17, 17, 17},
	{4, 0, 12, 4, 4, 4, 14},
	{2, 0, 6, 2, 2, 18, 12},
	{16, 16, 18, 20, 24, 20, 18},
	{12, 4, 4, 4, 4, 4, 14},
	{0, 0, 26, 21, 21, 17, 17},
	{0, 0, 22, 25, 17, 17, 17},
	{0, 0, 14, 17, 17, 17, 14},
	{0, 0, 30, 17, 30, 16, 16},
	{0, 0, 13, 19, 15, 1, 1},
	{0, 0, 22, 25, 16, 16, 16},
	{0, 0, 15, 16, 14, 1, 30},
	{8, 8, 28, 8, 8, 9, 6},
	{0, 0, 17, 17, 17, 19, 13},
	{0, 0, 17, 17, 17, 10, 4},
	{0, 0, 17, 17, 21, 21, 10},
	{0, 0, 17, 10, 4, 10, 17},
	{0, 0, 17, 17, 15, 1, 14},
	{0, 0, 31, 2, 4, 8, 31},
	{2, 4, 4, 8, 4, 4, 2},
	{4, 4, 4, 4, 4, 4, 4},
	{8, 4, 4, 2, 4, 4, 8},
	{0, 4, 2, 31, 2, 4, 0},
	{0, 4, 8, 31, 8, 4, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 0, 0, 0},
	{0, 0, 0, 0, 28, 20, 28},
	{7, 4, 4, 4, 0, 0, 0},
	{0, 0, 0, 4, 4, 4, 28},
	{0, 0, 0, 0, 16, 8, 4},
	{0, 0, 0, 12, 12, 0, 0},
	{0, 31, 1, 31, 1, 2, 4},
	{0, 0, 31, 1, 6, 4, 8},
	{0, 0, 2, 4, 12, 20, 4},
	{0, 0, 4, 31, 17, 1, 6},
	{0, 0, 0, 31, 4, 4, 31},
	{0, 0, 2, 31, 6, 10, 18},
	{0, 0, 8, 31, 9, 10, 8},
	{0, 0, 0, 14, 2, 2, 31},
	{0, 0, 30, 2, 30, 2, 30},
	{0, 0, 0, 21, 21, 1, 6},
	{0, 0, 0, 0, 31, 0, 0},
	{31, 1, 5, 6, 4, 4, 8},
	{1, 2, 4, 12, 20, 4, 4},
	{4, 31, 17, 17, 1, 2, 4},
	{0, 0, 31, 4, 4, 4, 31},
	{2, 31, 2, 6, 10, 18, 2},
	{8, 31, 9, 9, 9, 9, 18},
	{4, 31, 4, 31, 4, 4, 4},
	{0, 15, 9, 17, 1, 2, 12},
	{8, 15, 18, 2, 2, 2, 4},
	{0, 31, 1, 1, 1, 1, 31},
	{10, 31, 10, 10, 2, 4, 8},
	{0, 24, 1, 25, 1, 2, 28},
	{0, 31, 1, 2, 4, 10, 17},
	{8, 31, 9, 10, 8, 8, 7},
	{0, 17, 17, 9, 1, 2, 12},
	{0, 15, 9, 21, 3, 2, 12},
	{2, 28, 4, 31, 4, 4, 8},
	{0, 21, 21, 1, 1, 2, 4},
	{14, 0, 31, 4, 4, 4, 8},
	{8, 8, 8, 12, 10, 8, 8},
	{4, 4, 31, 4, 4, 8, 16},
	{0, 14, 0, 0, 0, 0, 31},
	{0, 31, 1, 10, 4, 10, 16},
	{4, 31, 2, 4, 14, 21, 4},
	{2, 2, 2, 2, 2, 4, 8},
	{0, 4, 2, 17, 17, 17, 17},
	{16, 16, 31, 16, 16, 16, 15},
	{0, 31, 1, 1, 1, 2, 12},
	{0, 8, 20, 2, 1, 1, 0},
	{4, 31, 4, 4, 21, 21, 4},
	{0, 31, 1, 1, 10, 4, 2},
	{0, 14, 0, 14, 0, 14, 1},
	{0, 4, 8, 16, 17, 31, 1},
	{0, 1, 1, 10, 4, 10, 16},
	{0, 31, 8, 31, 8, 8, 7},
	{8, 8, 31, 9, 10, 8, 8},
	{0, 14, 2, 2, 2, 2, 31},
	{0, 31, 1, 31, 1, 1, 31},
	{14, 0, 31, 1, 1, 2, 4},
	{18, 18, 18, 18, 2, 4, 8},
	{0, 4, 20, 20, 21, 21, 22},
	{0, 16, 16, 17, 18, 20, 24},
	{0, 31, 17, 17, 17, 17, 31},
	{0, 31, 17, 17, 1, 2, 4},
	{0, 24, 0, 1, 1, 2, 28},
	{4, 18, 8, 0, 0, 0, 0},
	{28, 20, 28, 0, 0, 0, 0},
	{0, 0, 9, 21, 18, 18, 13},
	{10, 0, 14, 1, 15, 17, 15},
	{0, 14, 17, 30, 17, 30, 16},
	{0, 0, 14, 16, 12, 17, 14},
	{0, 17, 17, 17, 19, 29, 16},
	{0, 0, 15, 20, 18, 17, 14},
	{0, 6, 9, 17, 17, 30, 16},
	{0, 15, 17, 17, 17, 15, 1},
	{0, 0, 7, 4, 4, 20, 8},
	{2, 26, 2, 0, 0, 0, 0},
	{2, 0, 6, 2, 2, 2, 2},
	{0, 20, 8, 20, 0, 0, 0},
	{4, 14, 20, 21, 14, 4, 0},
	{8, 8, 28, 8, 28, 8, 15},
	{14, 0, 22, 25, 17, 17, 17},
	{10, 0, 14, 17, 17, 17, 14},
	{0, 22, 25, 17, 17, 30, 16},
	{0, 13, 19, 17, 17, 15, 1},
	{14, 17, 31, 17, 17, 14, 0},
	{0, 0, 0, 0, 11, 21, 26},
	{0, 14, 17, 17, 10, 27, 0},
	{10, 0, 17, 17, 17, 19, 13},
	{31, 16, 8, 4, 8, 16, 31},
	{0, 31, 10, 10, 10, 19, 0},
	{31, 0, 17, 10, 4, 10, 17},
	{0, 17, 17, 17, 17, 15, 1},
	{1, 30, 4, 31, 4, 4, 0},
	{0, 31, 8, 15, 9, 17, 0},
	{0, 31, 21, 31, 17, 17, 0},
	{0, 0, 4, 0, 31, 0, 4},
	{0, 0, 0, 0, 0, 0, 0},
	{31, 31, 31, 31, 31, 31, 31}
};
